/*
 * TrCompat.h
 *  
 * The following stuff is basically a minimum of convenience stuff from my 
 * inhouse software framework called Tropic. This is taken from the core layer,
 * which provides compiler abstraction, vector and matrix maths, string 
 * manipulation, debug tracing, rational number classes, an exception framework,
 * all sort of STL utilities, and so on. It is basically what ilmbase from the
 * OpenEXR SDK is to ILM's Zeno system if you are familiar with that.
 *
 * We check for the inclusion guard defines of the corresponding header files, 
 * and if they are not present, we just re-implement the bare minimum here to 
 * make stuff compile without dragging the whole core layer along.
 *
 * Created by Peter on 22.02.12.
 * Copyright 2012-2014 __MyCompanyName__. All rights reserved.
 *
 */
#ifndef TR_COMPAT_H
#define TR_COMPAT_H

#include <iostream>

// UNIX header for uint16_t etc.
#if defined( __APPLE__ ) || defined( __linux__ )
	#include <stdint.h>
#endif

// On Linux, the builtin stdlib assert needs this header
#if defined( __linux__ )
	#include <assert.h>
#endif

/*
 * Debug Tracing. Trace macros that support stream io syntax when passing 
 * arguments.
 *
 * Source: /core/DbgTrace.h
 */
#ifndef TR_TRACE_H

	// Use this macro to trace stuff to the console in debug builds. You can write things like
	// TR_TRACE( "The value is " << x << " meters." );, which can be quite handy.
	#if defined( _DEBUG ) || defined( DEBUG )
		#define TR_TRACE( message ) std::clog << message << std::endl
	#else
		#define TR_TRACE( x )
	#endif

	// TODO: Let's replace the current ugly spaghetti indentation mess with 
    //       something like the Tropic::DbgTraceStream class that provides 
	//       proper indentation.

#endif

/*
 * These are a minimal version of our assertion macros.
 * Source: /core/DbgAssert.h
 */
#ifndef TR_ASSERT_H

	// Simple assertion macro. The Tropic version is much more fancy, but this will do for now.
	#define TR_ASSERT( x ) assert( x )

	// Check macro. These are like assertions, but they get compiled out of release builds.
	#if defined( _DEBUG ) || defined( DEBUG )
		#define TR_CHECK( x ) TR_ASSERT( x )
	#else
		#define TR_CHECK( x )
	#endif

    // Current function name. Might require ifdefs for certain compilers, the
    // full version from Tropic is too complex to be worth the overhead of
    // including it here.
    #define TR_CURRENT_FUNCTION __func__

    // You can put this in function stub bodies
    #define TR_NOT_IMPLEMENTED() TR_TRACE( __func__ << ": Not implemented." )

#endif

/*
 * Integer types of fixed sizes (use these for File IO etc.). Tropic also 
 * includes ILM half as Float16, but we don't need to have all that unless Avid 
 * sunddenly adds 16-bit support.
 *
 * Source: /core/SysTypes.h
 *
 * FIXME: This might require additional includes on certain platforms
 */
#ifndef TR_SYS_TYPES_H

	#ifdef _MSC_VER
		typedef unsigned __int64 UInt64;
		typedef unsigned __int32 UInt32;
		typedef unsigned __int16 UInt16;
		typedef unsigned __int8  UInt8;

		typedef __int8  Int8;
		typedef __int16 Int16;
		typedef __int32 Int32;
		typedef __int64 Int64;
		// ...
	#else
		typedef uint64_t UInt64;
		typedef uint32_t UInt32;
		typedef uint16_t UInt16;
		typedef uint8_t  UInt8;

		typedef int8_t Int8;
		typedef int16_t Int16;
		typedef int32_t Int32;
		typedef int64_t Int64;
		// ...
	#endif

	// FIXME: Correct for 32-bit Intel only!!!!!
	//typedef half   Float16; // Don't have ILM's Imf/OpenEXR here
	typedef float       Float32;
	typedef double      Float64;
	typedef long double Float128;

#endif

#ifndef TR_SYS_DEFS_H

/*
 * From /core/SysDefs.h and the compiler abstraction headers. This is for 
 * compilers that are not C++0X-compliant yet.
 */

// Since not all compilers are C++0x compliant yet, here is the the workaround
// implementation, copied directly from the standard proposal.
//
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2214.pdf
//
#ifndef __CPP09NULLPTRSUPPORTED
const    // this is a const object...
class {
public:
    template< class T >    // convertible to any type
    operator T*() const    // of null non-member
    { return 0; }    // pointer...
    
    template< class C, class T >  // or any type of null
    operator T C::*() const    // member pointer...
    { return 0; }
    
private:
    void operator&() const;    // whose address can't be taken
} nullptr = {};    // and whose name is nullptr
#endif

/*
 * Operating system abstraction (only needed for library import/export so far,
 * libAvid itself is cross platform.
 *
 * Taken from /core/SysDefs.h
 */
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(WINDOWS) || defined(WIN64) || defined(__WIN64__) || defined(_WIN64) || defined(WINNT)

    #define TROPIC_OS_WINDOWS

#elif defined(LINUX) || defined(linux) || defined(__linux) || defined(__linux__)

    #define TROPIC_OS_LINUX
    #define TROPIC_OS_UNIX

#elif defined(__APPLE__)

    /*This include file is present on both iOS and Desktop OS X*/
    #include <TargetConditionals.h>

    #if TARGET_OS_IPHONE
        #define TROPIC_OS_IOS
    #else
        #define TROPIC_OS_MAC
    #endif

#elif defined(Macintosh) || defined(macintosh) || defined(macos)

    // Probably 68k or something, modern OS X'es have __APPLE__ defined
    #define TROPIC_OS_MAC

#elif defined(IRIX) || defined(__sgi) || defined(sgi)

    #define TROPIC_OS_IRIX
    #define TROPIC_OS_UNIX

#elif defined(BEOS) || defined(__BEOS__) || defined(__HAIKU__)

    #define TROPIC_OS_BEOS

#elif defined(OS2)

    #define TROPIC_OS_OS2

#else

    #pragma warning Operating system not supported in SysDefs.h!

#endif


/*
 * Endianity defines and library import/export from /core/SysDefs.h and the
 * compiler abstraction headers (only GCC and MSVC, skipping Borland, MIPSPro etc.).
 */
#ifdef __GNUC__

    // Endianity
	#ifdef __BIG_ENDIAN__
		#define TR_BIG_ENDIAN
	#else
		#define TR_LITTLE_ENDIAN
	#endif

    // Library import/export
    #if defined( TROPIC_OS_WINDOWS )
        // Both MSC and Windows-GCC builds (MinGW, Cygwin) support this.
        #define TR_IMPORT __declspec( dllimport )
        #define TR_EXPORT __declspec( dllexport )
    #elif defined( TROPIC_OS_MAC )
        // Don't be deceived by the word "default", this means that the symbol is
        // always exported, no matter what the value of the -fvisibility flag is.
        #define TR_IMPORT
        #define TR_EXPORT __attribute__((visibility("default")))
    #else
        // These specifiers are not needed (nor consistently supported) on other
        // platforms gcc runs on.
        #define TR_IMPORT
        #define TR_EXPORT
    #endif

#endif

#ifdef _MSC_VER

    // Endianity
	#if defined(_M_IX86) || defined(_M_X64)
		#define TR_LITTLE_ENDIAN
	#else
		#define TR_BIG_ENDIAN
	#endif

    // Library import/export
    #define TR_IMPORT __declspec(dllimport)
    #define TR_EXPORT __declspec(dllexport)

#endif

#ifdef __BORLANDC__

    // FIXME: Endianity missing here!!!

    // Library import/export
    #define TR_IMPORT __declspec(dllimport)
    #define TR_EXPORT __declspec(dllexport)

#endif

#endif /*Tropic::core SysDefs header present*/

#endif /*Inclusion Guard*/